# coding=utf-8
import math


class Item(object):
    '''
    多项式中的项
    '''

    def __init__(self, m, p):
        self.m = m
        self.p = p

    def product(self, other):
        if isinstance(other, Poliminal):
            return other.product(self)
        return Item(self.m * other.m, self.p + other.p)

    def add(self, other):
        arr = []
        if isinstance(other, Poliminal):
            return other.add(self)
        else:
            arr.append(other)
        arr.append(self)
        return Poliminal(arr)

    def __str__(self):
        r = ""
        if self.p == 0:
            r = "{}".format(self.m)
        elif self.p == 1:
            r = "{}x".format(self.m)
        else:
            r = "{}x^{}".format(self.m, self.p)
        return "0" if r == "" else r

    def __cmp__(self, other):
        return other.p - self.p

    def __eq__(self, other):
        if not isinstance(other, Item):
            return False
        return self.m == other.m and self.p == other.p


class Poliminal(object):
    '''
    多项式
    '''

    def __init__(self, items):
        self.items = [it for it in items if it.m != 0]
        self.__tidy()

    def product(self, other):
        items = []
        if isinstance(other, Item):
            other = Poliminal([other])
        for it in self.items:
            for it2 in other.items:
                items.append(it.product(it2))
        return Poliminal(items)

    def add(self, poliminal):
        if isinstance(poliminal, Item):
            poliminal = Poliminal([poliminal])
        items = self.items + poliminal.items
        return Poliminal(items)

    def __tidy(self):
        d = dict()
        for it in self.items:
            if it.p in d:
                d[it.p] += it.m
            else:
                d[it.p] = it.m
        self.items = [Item(d[p], p) for p in d]

    def derivate(self):
        '''
        求导
        '''
        r = []
        for it in self.items:
            m = it.m
            p = it.p
            r.append(Item(m * p, p - 1))
        return Poliminal(r)

    def __str__(self):
        self.items.sort()
        r = ""
        for i in range(0, len(self.items)):
            it = self.items[i]
            if it.m > 0:
                if i == 0:
                    r += str(it)
                else:
                    r += ("+" + str(it))
            else:
                r += str(it)
        return "0" if r == "" else r

    def __eq__(self, other):
        if not isinstance(other, Poliminal):
            return False
        self.__tidy()
        other.__tidy()
        return self.items == other.items

if __name__ == '__main__':
    item = Item(7, 2)
    item2 = Item(-1, 1)
    item3 = Item(3, 0)
    item4 = Item(6, 2)
    item5 = Item(3, 1)
    item6 = Item(6, 0)
    item7 = Item(-5, 0)
    poliminal = item.add(item2).add(item3)
    poliminal2 = item4.add(item5).add(item6)
    print poliminal.product(poliminal2).derivate()
    print poliminal.product(poliminal2.derivate()).add(poliminal.derivate().product(poliminal2))
